######################################
# Game Data
######################################
class ProleagueGameData(object):
    """Data of a game for a game specification to try to match against.

    Has information regarding a specific game. A dictionary of values regarding
    the information of a game can be passed to the matches_spec method to
    determine if this game could be the game that the spec is talking about.
    """

    def __init__(self, league, stage_path, match_id, game_number,
            team_one, team_two, date_played, player_one, player_two):

        self.league = league
        self.stage_path = stage_path
        self.match_id = match_id
        self.game_number = game_number

        self.team_one = team_one
        self.team_two = team_two

        self.date_played = date_played
        self.player_one = player_one
        self.player_two = player_two

    def matches_spec(self, spec):
        if 'date_played' in spec and len(spec['date_played']) > 0:
            if self.date_played not in spec['date_played']:
                return False

        if 'teams' in spec:
            for team in spec['teams']:
                if team != self.team_one and team != self.team_two:
                    return False

        if 'players' in spec:
            for player in spec['players']:
                if player != self.player_one and player != self.player_two:
                    return False

        if 'game_number' in spec and len(spec['game_number']) > 0:
            if self.game_number not in spec['game_number']:
                return False

        return True

    def make_found_dict(self):
        return {
            'match_id' : self.match_id,
            'game_number' : self.game_number,
        }

    def make_possible_dict(self):
        return {
            'league' : self.league,
            'stage_path' : self.stage_path,
            'match_id' : self.match_id,
            'team_one' : self.team_one,
            'team_two' : self.team_two,
            'date_played' : self.date_played,
            'player_one' : self.player_one,
            'player_two' : self.player_two,
            'game_number' : self.game_number,
        }
            

class GameSearchResult(object):
    def __init__(self, found, data):
        self.found = found
        self.data = data

class GameSearchRepository(object):
    """Search known games for games matching a specification.

    Add matches and games to store them, then search by using the find_game
    method.
    """

    def __init__(self, store):
        self.matches = store.setdefault('matches', {})
        self.games = store.setdefault('games', {})

    def add_proleague_match(self, match_id, league, stage_path,
            team_one, team_two):

        data = {
            'league' : league,
            'stage_path' : stage_path,
            'team_one' : team_one,
            'team_two' : team_two
        }

        self.matches[match_id] = data

    def set_game(self, match_id, game_number, date_played,
            player_one, player_two):

        match_data = self.matches[match_id]

        data = ProleagueGameData(match_data['league'],
                match_data['stage_path'], match_id, game_number,
                match_data['team_one'], match_data['team_two'],
                date_played, player_one, player_two)

        key = (match_id, game_number)
        self.games[key] = data

    def find_game(self, spec):
        """Find a game or list of games matching the spec.

        The spec is a dictionary with each value being a list of possible values
        for that name. Possible names are:
            date_played: The date that the game was played.
            players: The players in the game.
            teams: The teams in the game.
            game_number: The game number in the match.
        """
        filter_func = lambda (k,v): v.matches_spec(spec)
        results = filter(filter_func, self.games.items())

        if len(results) == 1:
            return GameSearchResult(True, results[0][1].make_found_dict())
        else:
            possible_results = [x[1].make_possible_dict() for x in results]
            data = spec.copy()
            data['possible_results'] = possible_results
            return GameSearchResult(False, data)



